package com.yanghui.blueteethscreen.driver

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothSocket
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import kotlinx.coroutines.*
import java.io.InputStream
import java.io.OutputStream
import java.util.*
import kotlin.concurrent.thread

object BlueToothDriver {

    /**
     * 蓝牙适配器
     */
    private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
    private val bluetoothDeviceList = LinkedList<BluetoothDevice>()
    private var bluetoothConnected = false
    private var bluetoothBondedFound = false
    private var bluetoothReceiver: BroadcastReceiver? = null
    private lateinit var bluetoothSocket: BluetoothSocket
    private lateinit var bluetoothInputStream: InputStream
    private lateinit var bluetoothOutputStream: OutputStream
    private var bluetoothReadMethod: (ByteArray, Int) -> Unit = {_, _ ->}

    fun init(parentContext: Context, deviceName: String) {
        if (bluetoothAdapter == null) {
            throw BlueToothException("该设备不支持蓝牙")
        }
        /* 蓝牙处于未启动模式 */
        if (!bluetoothAdapter.isEnabled) {
            bluetoothAdapter.enable()
        }
        Thread.sleep(100)
        /* 首先获取已经配对了的蓝牙设备 */
        bluetoothDeviceList.addAll(bluetoothAdapter.bondedDevices)
        if (checkDevice(deviceName, parentContext))
            return
        /* 蓝牙处于非扫描模式 */
        if (!bluetoothAdapter.isDiscovering) {
            bluetoothAdapter.startDiscovery()
        }
        /* 注册一个蓝牙发现事件 */
        val intentFilter = IntentFilter(BluetoothDevice.ACTION_FOUND)
        bluetoothReceiver = BlueToothReceiver { context, intent ->
            intent ?: return@BlueToothReceiver
            context ?: return@BlueToothReceiver
            if (BluetoothDevice.ACTION_FOUND == intent.action) {
                intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)?.let {
                    bluetoothDeviceList.add(it)
                }
                checkDevice(deviceName, context)
            }
        }
        parentContext.registerReceiver(bluetoothReceiver, intentFilter)
    }

    fun write(bytes: ByteArray) {
        if (bluetoothConnected)
            bluetoothOutputStream.write(bytes)
    }

    fun registerRead(method: (ByteArray, Int) -> Unit) {
        bluetoothReadMethod = method
    }

    private fun checkDevice(deviceName: String, context: Context?): Boolean {
        if (bluetoothAdapter == null) {
            throw BlueToothException("该设备不支持蓝牙")
        }

        //TODO: DEBUG
        val list: LinkedList<String> = LinkedList()
        bluetoothDeviceList.forEach {
            list.add(it.name)
        }

        /* 轮询检查所有的蓝牙设备 */
        var targetDevice: BluetoothDevice? = null
        for (d in bluetoothDeviceList) {
            if (d.name == deviceName) {
                targetDevice = d
                break
            }
        }
        targetDevice?.let {
            if (bluetoothAdapter.isDiscovering) {
                bluetoothAdapter.cancelDiscovery()
            }
            bluetoothReceiver?.let {
                context?.unregisterReceiver(it)
            }

            bluetoothSocket =
                targetDevice.createRfcommSocketToServiceRecord(
                    UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
                )
            GlobalScope.launch(Dispatchers.IO) {
                thread {
                    bluetoothSocket.connect()
                    bluetoothConnected = true
                }
                while(!bluetoothConnected) {
                    delay(100)
                }
                bluetoothInputStream = bluetoothSocket.inputStream
                bluetoothOutputStream = bluetoothSocket.outputStream

                if (bluetoothAdapter.isDiscovering) {
                    bluetoothAdapter.cancelDiscovery()
                }

                GlobalScope.launch(Dispatchers.IO) {
                    val bytes = ByteArray(1024)
                    while (true) {
                        val len = bluetoothInputStream.read(bytes)
                        if (len != -1) {
                            bluetoothReadMethod(bytes, len)
                        }
                    }
                }
            }
            return true
        }
        return false
    }
}

class BlueToothReceiver(
    val method: (context: Context?, intent: Intent?) -> Unit
) : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        method(context, intent)
    }

}

class BlueToothException(message: String = "错误") : Exception(message)